feat(plugins): warn when env plugin shadows a registry tool#7953
Conversation
Add a --lock flag that resolves and embeds lockfile data (exact version + platform URLs/checksums) directly into tool stub files. This makes stubs fully reproducible without runtime API calls, which is especially useful for avoiding GitHub API rate limits. Also supports --version with --lock to bump versions in locked stubs. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Summary of ChangesHello @jdx, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Pull request overview
This PR adds a warning when vfox env-only plugins shadow registry tools, and implements a locking mechanism for tool stubs to enable reproducible installs without runtime API calls.
Changes:
- Detects env-only vfox plugins (having
mise_env.luabut notavailable.lua) and warns when their name matches a registry entry - Adds
--lockflag tomise generate tool-stubfor pinning exact versions and platform-specific URLs/checksums - Implements lock data injection from tool stubs into the toolset resolution process
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/plugins/vfox_plugin.rs | Adds warning method for env plugins shadowing registry tools, called after plugin installation |
| src/cli/plugins/install.rs | Adds duplicate warning function for asdf plugins and calls it after installation |
| src/cli/tool_stub.rs | Adds lock data structures and injection logic to populate tool versions with locked platform info |
| src/cli/generate/tool_stub.rs | Implements --lock flag to resolve versions and generate lock sections with platform URLs/checksums |
| e2e/plugins/test_env_plugin_shadow_warning | E2E test verifying warning appears when installing env plugin matching registry name |
| e2e/generate/test_generate_tool_stub_lock | E2E tests for tool stub locking functionality including version bumping and idempotency |
| docs/dev-tools/tool-stubs.md | Documents the new locking feature with examples of usage and benefits |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/cli/plugins/install.rs
Outdated
| fn warn_if_env_plugin_shadows_registry(name: &str, plugin_path: &Path) { | ||
| let hooks = plugin_path.join("hooks"); | ||
| let is_env_only = hooks.join("mise_env.lua").exists() && !hooks.join("available.lua").exists(); | ||
| if is_env_only && REGISTRY.contains_key(name) { | ||
| warn!( | ||
| "plugin '{name}' is an env plugin and is shadowing the '{name}' registry tool - \ | ||
| consider renaming the plugin or removing it with: mise plugins rm {name}" | ||
| ); | ||
| } | ||
| } |
There was a problem hiding this comment.
This function duplicates the logic from VfoxPlugin::warn_if_env_plugin_shadows_registry. Consider extracting the common warning logic into a shared utility function to avoid code duplication and ensure consistent behavior across both plugin types.
| Ok(info) if info.url.is_some() => { | ||
| lock_platforms.insert(target.to_key(), info); | ||
| } | ||
| _ => {} // Skip platforms without lock info |
There was a problem hiding this comment.
Silent failures for platforms without lock info could make debugging difficult. Consider logging a debug or trace message indicating which platforms were skipped and why.
|
|
||
| // Inject lock data from stub into tool versions | ||
| if let Some(lock) = &stub.lock { | ||
| for (_ba, tvl) in toolset.versions.iter_mut() { |
There was a problem hiding this comment.
The variable name _ba is unclear. Consider renaming it to _backend_alias or _tool_backend to better indicate what it represents, even though it's unused.
| for (_ba, tvl) in toolset.versions.iter_mut() { | |
| for (_backend_alias, tvl) in toolset.versions.iter_mut() { |
There was a problem hiding this comment.
Code Review
This pull request introduces two main features: a warning for environment-only vfox plugins that shadow registry tools, and a new --lock flag for mise generate tool-stub to create reproducible tool stubs. The changes are well-implemented and include corresponding documentation and tests. My review focuses on improving code maintainability by addressing a small amount of code duplication. Overall, this is a solid contribution.
src/plugins/vfox_plugin.rs
Outdated
| /// Warn if this is an env-only plugin whose name matches a registry entry. | ||
| fn warn_if_env_plugin_shadows_registry(&self) { | ||
| let hooks = self.plugin_path.join("hooks"); | ||
| let is_env_only = | ||
| hooks.join("mise_env.lua").exists() && !hooks.join("available.lua").exists(); | ||
| if is_env_only && REGISTRY.contains_key(self.name.as_str()) { | ||
| warn!( | ||
| "plugin '{}' is an env plugin and is shadowing the '{}' registry tool - \ | ||
| consider renaming the plugin or removing it with: mise plugins rm {}", | ||
| self.name, self.name, self.name | ||
| ); | ||
| } | ||
| } |
There was a problem hiding this comment.
This function warn_if_env_plugin_shadows_registry duplicates logic also found in src/cli/plugins/install.rs. To adhere to the DRY (Don't Repeat Yourself) principle and improve maintainability, this logic should be extracted into a single, shared utility function.
A new function like pub fn warn_if_vfox_env_plugin_shadows_registry(name: &str, plugin_path: &Path) could be created in a shared module (e.g., src/plugins/util.rs) and then called from both this location and install.rs.
When a vfox env-only plugin (has hooks/mise_env.lua but not hooks/available.lua) is installed with a name that matches a registry entry, emit a warning at install time. This helps prevent users from accidentally shadowing registry tools with env plugins. The warning fires in two places: - CLI plugin install (mise plugins install) - VfoxPlugin::ensure_installed (auto-install from config) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
0e762ae to
7d86492
Compare
|
bugbot run |
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.0 x -- echo |
20.4 ± 0.4 | 19.7 | 23.4 | 1.00 |
mise x -- echo |
21.0 ± 0.5 | 20.0 | 22.9 | 1.03 ± 0.03 |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.0 env |
20.1 ± 0.6 | 19.2 | 24.6 | 1.00 |
mise env |
20.4 ± 0.4 | 19.4 | 21.9 | 1.02 ± 0.04 |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.0 hook-env |
20.7 ± 0.3 | 20.0 | 22.1 | 1.00 |
mise hook-env |
21.4 ± 0.5 | 20.4 | 23.8 | 1.03 ± 0.03 |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.0 ls |
18.6 ± 0.4 | 17.8 | 19.8 | 1.00 |
mise ls |
19.0 ± 0.4 | 18.1 | 20.8 | 1.02 ± 0.03 |
xtasks/test/perf
| Command | mise-2026.2.0 | mise | Variance |
|---|---|---|---|
| install (cached) | 112ms | 113ms | +0% |
| ls (cached) | 71ms | 71ms | +0% |
| bin-paths (cached) | 75ms | 76ms | -1% |
| task-ls (cached) | 535ms | 537ms | +0% |
The test_env_plugin_shadow_warning test creates a git repo and needs to commit, which fails in CI where no git identity is configured. Set GIT_AUTHOR_NAME/EMAIL and GIT_COMMITTER_NAME/EMAIL in the e2e test harness so all tests can use git commit without extra config. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
a969c71 to
449e1d1
Compare
| if let Some(lock) = &stub.lock { | ||
| for (_ba, tvl) in toolset.versions.iter_mut() { | ||
| for tv in &mut tvl.versions { | ||
| if tv.ba().short == stub.tool_name { |
There was a problem hiding this comment.
Lock injection fails for aliased tool names silently
Medium Severity
The comparison tv.ba().short == stub.tool_name uses inconsistent aliasing. stub.tool_name is stored directly from the stub's tool field without unaliasing (e.g., "nodejs", "golang", "core:node"). However, tv.ba().short is derived from a BackendArg that applies unalias_backend() during construction (converting "nodejs" to "node", "golang" to "go", stripping "core:" prefix). This causes the comparison to fail silently for any aliased tool name, preventing lock data injection.
Extract the shared warning function into plugins/mod.rs and use it from both install.rs and vfox_plugin.rs. Also move the warning call inside the `if !dry_run` block in vfox_plugin.rs. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
### 🚀 Features - **(generate)** implement --index flag and use task names for task-docs --multi by @jdx in [#7944](#7944) - **(plugins)** warn when env plugin shadows a registry tool by @jdx in [#7953](#7953) - **(tool-stub)** add --lock flag to generate tool-stub by @jdx in [#7948](#7948) - **(vfox)** add log module for Lua plugins by @jdx in [#7949](#7949) - **(vfox)** switch Lua runtime from Lua 5.1 to Luau by @jdx in [#7954](#7954) ### 🐛 Bug Fixes - **(build)** upgrade cross images to :main for C++17 support by @jdx in [#7958](#7958) - **(build)** update glibc check to match new cross image baseline by @jdx in [fc1247e](fc1247e) - **(registry)** handle file:// URLs in normalize_remote by @jdx in [#7947](#7947) - **(vfox)** fix LuaLS warnings in test fixtures and add linting by @jdx in [#7946](#7946) ### 🚜 Refactor - unify deprecated_at! macro with warn and remove versions by @jdx in [#7957](#7957) ### 🧪 Testing - remove unnecessary end-of-test cleanup from e2e tests by @jdx in [#7950](#7950) ###◀️ Revert - Revert "fix(build): update glibc check to match new cross image baseline" by @jdx in [0774bf9](0774bf9) - Revert "fix(build): upgrade cross images to :main for C++17 support " by @jdx in [8dcca08](8dcca08) - Revert "feat(vfox): switch Lua runtime from Lua 5.1 to Luau " by @jdx in [8b4322d](8b4322d)
## Summary - Adds a warning when a vfox env-only plugin is installed with a name that matches a registry entry - Env-only plugins are detected by having `hooks/mise_env.lua` but not `hooks/available.lua` - Warning fires at install time only (not on every resolution) to avoid noise - Covers both CLI install (`mise plugins install`) and auto-install via `VfoxPlugin::ensure_installed` ## Test plan - [x] Added e2e test `test_env_plugin_shadow_warning` that creates a fake vfox env plugin named "jq" and verifies the warning appears - [x] Unit tests pass (444/444) - [x] Lint passes 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk because it changes tool-stub resolution/installation behavior by injecting per-platform lock data and adds new mutation paths for existing stub files; it also touches plugin install flows (new warning) and adds new e2e coverage. > > **Overview** > **Tool stubs can now be “locked” for reproducible installs.** `mise generate tool-stub --lock` updates an existing stub by resolving the exact version and writing a `[lock.platforms.*]` table with pinned URLs/checksums (and supports bumping via `--version`), and `mise tool-stub` consumes this lock data during installation. > > **Plugin installs now warn on name collisions.** When installing an env-only vfox plugin (has `hooks/mise_env.lua` but no `hooks/available.lua`) whose name matches a registry tool, mise emits a one-time warning during install. > > Docs/man/completions are updated for `--lock`, and e2e tests are expanded (new lock/warning tests, more reliable HTTP upgrade test via random port, and git author env for test commits). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit c5eff4a. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
### 🚀 Features - **(generate)** implement --index flag and use task names for task-docs --multi by @jdx in [jdx#7944](jdx#7944) - **(plugins)** warn when env plugin shadows a registry tool by @jdx in [jdx#7953](jdx#7953) - **(tool-stub)** add --lock flag to generate tool-stub by @jdx in [jdx#7948](jdx#7948) - **(vfox)** add log module for Lua plugins by @jdx in [jdx#7949](jdx#7949) - **(vfox)** switch Lua runtime from Lua 5.1 to Luau by @jdx in [jdx#7954](jdx#7954) ### 🐛 Bug Fixes - **(build)** upgrade cross images to :main for C++17 support by @jdx in [jdx#7958](jdx#7958) - **(build)** update glibc check to match new cross image baseline by @jdx in [fc1247e](jdx@fc1247e) - **(registry)** handle file:// URLs in normalize_remote by @jdx in [jdx#7947](jdx#7947) - **(vfox)** fix LuaLS warnings in test fixtures and add linting by @jdx in [jdx#7946](jdx#7946) ### 🚜 Refactor - unify deprecated_at! macro with warn and remove versions by @jdx in [jdx#7957](jdx#7957) ### 🧪 Testing - remove unnecessary end-of-test cleanup from e2e tests by @jdx in [jdx#7950](jdx#7950) ###◀️ Revert - Revert "fix(build): update glibc check to match new cross image baseline" by @jdx in [0774bf9](jdx@0774bf9) - Revert "fix(build): upgrade cross images to :main for C++17 support " by @jdx in [8dcca08](jdx@8dcca08) - Revert "feat(vfox): switch Lua runtime from Lua 5.1 to Luau " by @jdx in [8b4322d](jdx@8b4322d)


Summary
hooks/mise_env.luabut nothooks/available.luamise plugins install) and auto-install viaVfoxPlugin::ensure_installedTest plan
test_env_plugin_shadow_warningthat creates a fake vfox env plugin named "jq" and verifies the warning appears🤖 Generated with Claude Code
Note
Medium Risk
Medium risk because it changes tool-stub resolution/installation behavior by injecting per-platform lock data and adds new mutation paths for existing stub files; it also touches plugin install flows (new warning) and adds new e2e coverage.
Overview
Tool stubs can now be “locked” for reproducible installs.
mise generate tool-stub --lockupdates an existing stub by resolving the exact version and writing a[lock.platforms.*]table with pinned URLs/checksums (and supports bumping via--version), andmise tool-stubconsumes this lock data during installation.Plugin installs now warn on name collisions. When installing an env-only vfox plugin (has
hooks/mise_env.luabut nohooks/available.lua) whose name matches a registry tool, mise emits a one-time warning during install.Docs/man/completions are updated for
--lock, and e2e tests are expanded (new lock/warning tests, more reliable HTTP upgrade test via random port, and git author env for test commits).Written by Cursor Bugbot for commit c5eff4a. This will update automatically on new commits. Configure here.